﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace iMario
{
    public class KindOfSprite
    {
        //Mục đích class KindOfSprite
        //  - Chứa thông tin sprite về loại sprite (loại nhân vật, loại character, loại đạn...)

        //Danh sách các thuộc tính và ý nghĩa
        static private ContentManager _content = null;      //Địa chỉ biến Content Game được sử dụng
        public const int LEFT = 4;
        public const int RIGHT = 6;
        public const int JUMPLEFT = 9;
        public const int JUMPRIGHT = 7;

        static private String _spritesName;                 //Tên loại Sprite
        public static String spritesName
        {
            get { return KindOfSprite._spritesName; }
        }
        
        private List<Texture2D> _spriteLeft;                //Danh sách các frame hình đại diện cho loại sprite nhìn về bên trái
        public List<Texture2D> spriteLeft
        {
            get { return _spriteLeft; }
        }

        private List<Texture2D> _spriteRight;               //Danh sách các frame hình đại diện cho loại sprite nhìn về bên phải
        public List<Texture2D> spriteRight
        {
            get { return _spriteRight; }
        }

        private List<Texture2D> _spriteJumpLeft;            //Danh sách các frame hình đại diện cho loại sprite nhảy sang trái
        public List<Texture2D> spriteJumpLeft
        {
            get { return _spriteJumpLeft; }
        }

        private List<Texture2D> _spriteJumpRight;           //Danh sách các frame hình đại diện cho loại sprite nhảy sang phải
        public List<Texture2D> spriteJumpRight
        {
            get { return _spriteJumpRight; }
        }

        private Point _size;                                //Kích thước của sprite trên màn hình game, với x tương đương width và y tương đương heigh
        public Point size
        {
            get { return _size; }
        }

        private List<Texture2D> _shotTexture;               //Danh sách các frame hình đại diện cho loại đạn mà loại sprite này bắn được
        public List<Texture2D> shotTexture
        {
            get { return _shotTexture; }
        }

        private bool _canShot;                              //Cờ hiệu cho phép loại Sprite2D được bắn
        public bool canShot
        {
            get { return _canShot; }
        }

        private int _maxHeighJump;                          //Chiều cao tối đa loại Sprite2D có thể nhảy được
        public int maxHeighJump
        {
            get { return _maxHeighJump; }
        }

        private Point _speed;                                //Tốc độ di chuyển của loại sprite; x - Tốc độ di chuyển trên phương ngang; y - Tốc độ di chuyển trên phương đứng
        public Point speed
        {
            get { return _speed; }
            set { _speed = value; }
        }

        //Danh sách các phương thức và ý nghĩa
        //Hàm dựng có truyền tham số - áp dụng cho loại nhân vật
        //  1. Tham số truyền vào:
        //      - String _name: tên loại sprite (không đánh số)
        //      - int _nSprite: số hình biểu diễn loại sprite được load
        //      - int _inputMaxHeighJump: Chiều cao tối đa loại nhân vật này có thể nhảy
        //      - Point _inputSize: kích thước của loại nhân vật
        //      - Point _inputSpeed: Tốc độ di chuyển theo phương ngang và phương dọc của loại sprite
        //  2. Giá trị trả về: Không có
        public KindOfSprite(String _name, int _nSprites, int _inputMaxHeighJump, bool _inputCanShot, Point _inputSize, Point _inputSpeed)
        { 
            //Hướng xử lí
            //Kiểm tra: Nếu biến _content khác null thì tiếp tục xử lí
            //  1. Khởi tạo danh sách frame hình _sprite ứng với số Texture đại diện cho loại sprite
            //  2. Thiết lập giá trị các thuộc tính khác


            //Tiến hành
            //Kiểm tra: Nếu biến _content khác null thì tiếp tục xử lí
            if (_content == null)
                return;
            
            //  1. Khởi tạo danh sách frame hình _sprite ứng với số Texture đại diện cho loại sprite
            _spriteLeft = new List<Texture2D>(_nSprites);
            _spriteRight = new List<Texture2D>(_nSprites);
            _spriteJumpLeft = new List<Texture2D>(_nSprites);
            _spriteJumpRight = new List<Texture2D>(_nSprites);

            //  2. Thiết lập giá trị các thuộc tính khác
            _maxHeighJump = _inputMaxHeighJump;
                        
            _canShot = _inputCanShot;

            _spritesName = _name;

            _shotTexture = new List<Texture2D>();

            _size = _inputSize;

            _speed = _inputSpeed;
        }

        //Hàm dựng có truyền tham số - áp dụng cho loại quái vật
        //  1. Tham số truyền vào:
        //      - String _name: tên loại sprite
        //      - int _nSprite: Số hình biểu diễn cho loại sprite được load
        //      - Point _inputSize: kích thước của loại nhân vật
        //  2. Giá trị trả về: Không có
        public KindOfSprite(String _name, int _nSprite, Point _inputSize)
        {
            //Hướng xử lí:
            //Kiểm tra: Nếu biến _content khác null thì tiếp tục xử lí
            //  1. Khởi tạo danh sách frame hình đại diện cho loại sprite
            //  2. Thiết lập giá trị của _spriteName


            //Tiến hành
            //Kiểm tra: Nếu biến _content khác null thì tiếp tục xử lí
            if (_content == null)
                return;

            //  1. Khởi tạo danh sách frame hình đại diện cho loại sprite
            _spriteLeft = new List<Texture2D>(_nSprite);
            _spriteRight = null;
            _spriteJumpLeft = null;
            _spriteJumpRight = null;

            //  2. Thiết lập giá trị của _spriteName
            _spritesName = _name;
        }

        //Hàm thiết lập địa chỉ biến Content được sử dụng trong Game1
        //  1. Tham số truyền vào
        //      - ContentManager _content
        //  2. Giá trị trả về: Không có
        static public void SetContent(ContentManager _inputContent)
        {
            _content = _inputContent;
        }

        //Hàm thiết lập tốc độ di chuyển theo từng phương của loại sprite
        //  1. Tham số truyền vào:
        //      - int _xSpeed: Tốc độ di chuyển trên phương ngang
        //      - int _ySpeed: Tốc độ di chuyển trên phương đứng
        //  2. Giá trị trả về: Không có
        public void SetSpeed(int _xSpeed, int _ySpeed)
        {
            _speed.X = _xSpeed;
            _speed.Y = _ySpeed;
        }

        //Hàm load các frame hình biểu diễn cho Sprite - dành cho loại nhân vật
        //  1. Tham số truyền vào:
        //      - int _way: đại diện cho 
        //  2. Giá trị trả về: Không có
        public void LoadContent(int _way)
        {
            //Hướng xử lí trong hàm LoadContent
            //Kiểm tra: Nếu _content != null => tiếp tục xử lí các lệnh bên dưới
            //  Load lần lượt từng texture2D có tên bắt đầu bằng _spriteName và đánh số từ 0 đến _sprite.Capacity - 1


            //Tiến hành
            //Kiểm tra: Nếu _content != null => tiếp tục xử lí các lệnh bên dưới
            if (_content == null)
                return;

            switch (_way)
            {
                case LEFT:
                    {
                        for (int i = 0; i < _spriteLeft.Capacity; i++)
                        {
                            String _fileName = _spritesName + "Left" + i.ToString("00");
                            _spriteLeft.Add(_content.Load<Texture2D>(@"Sprites/" + _fileName));
                        }

                        break;
                    }
                case RIGHT:
                    {
                        for (int i = 0; i < _spriteRight.Capacity; i++)
                        {
                            String _fileName = _spritesName + "Right" + i.ToString("00");
                            _spriteRight.Add(_content.Load<Texture2D>(@"Sprites/" + _fileName));
                        }

                        break;
                    }
                case JUMPLEFT:
                    {
                        for (int i = 0; i < _spriteJumpLeft.Capacity; i++)
                        {
                            String _fileName = _spritesName + "JumpLeft" + i.ToString("00");
                            _spriteJumpLeft.Add(_content.Load<Texture2D>(@"Sprites/" + _fileName));
                        }

                        break;
                    }
                case JUMPRIGHT:
                    {
                        for (int i = 0; i < _spriteJumpRight.Capacity; i++)
                        {
                            String _fileName = _spritesName + "JumpRight" + i.ToString("00");
                            _spriteJumpRight.Add(_content.Load<Texture2D>(@"Sprites/" + _fileName));
                        }

                        break;
                    }
            }
        }

        //Hàm load các frame hình biểu diễn cho Sprite - dành cho loại quái vật
        //  1. Tham số truyền vào: Không có
        //  2. Giá trị trả về: Không có
        public void LoadContent()
        {
            //Hướng xử lí trong hàm LoadContent
            //Kiểm tra: Nếu _content != null => tiếp tục xử lí các lệnh bên dưới
            //  Load lần lượt từng texture2D có tên bắt đầu bằng _spriteName và đánh số từ 0 đến _sprite.Capacity - 1


            //Tiến hành
            //Kiểm tra: Nếu _content != null => tiếp tục xử lí các lệnh bên dưới
            if (_content == null)
                return;

            //  Load lần lượt từng texture2D có tên bắt đầu bằng _spriteName và đánh số từ 0 đến _sprite.Capacity - 1
            for (int i = 0; i < _spriteLeft.Capacity; i++)
            {
                String _fileName = "Monster" + _spritesName + i.ToString("00");
                Texture2D _texture = _content.Load<Texture2D>(@"Sprites/" + _fileName);
            }
        }

        //Hàm xử lí các thao tác vẽ sprite lên màn hình game
        //  1. Tham số truyền vào
        //      - SpriteBatch _spriteBatch
        //      - int _iSprite: Chỉ số frame hình của Sprite sẽ được vẽ
        //      - Rectangle _clientRect: Khung bao quanh của sprite sẽ được vẽ (có tọa độ x, y và kích thước sprite)
        //      - int _way: Đại diện cho hướng vẽ nhân vật
        //  2. Giá trị trả về: Không có
        public void Draw(SpriteBatch _spriteBatch, int _iSprite, Rectangle _clientRect, int _way)
        {
            //Hướng xử lí
            //Kiểm tra và xử lí từng trường hợp vẽ: LEFT, RIGHT và JUMP
            //Kiểm tra: Nếu _iSprite < _sprite.Capacity => Tiếp tục xử lí các lệnh bên dưới
            //  Gọi hàm Draw của _spriteBatch để vẽ _sprite[_iSprite] theo _clientRect được truyền vào


            //Tiến hành
            //Kiểm tra và xử lí từng trường hợp vẽ: LEFT, RIGHT và JUMP
            switch (_way)
            {
                case LEFT:
                    {
                        //Kiểm tra: Nếu _iSprite < _nSprite => Tiếp tục xử lí các lệnh bên dưới
                        if (_iSprite < 0 || _iSprite > _spriteLeft.Capacity)
                            return;

                        //  Gọi hàm Draw của _spriteBatch để vẽ _sprite[_iSprite] theo _clientRect được truyền vào
                        _spriteBatch.Draw(_spriteLeft[_iSprite], _clientRect, Color.White);

                        break;
                    }
                case RIGHT:
                    {
                        //Kiểm tra: Nếu _iSprite < _nSprite => Tiếp tục xử lí các lệnh bên dưới
                        if (_iSprite < 0 || _iSprite > _spriteRight.Capacity)
                            return;

                        //  Gọi hàm Draw của _spriteBatch để vẽ _sprite[_iSprite] theo _clientRect được truyền vào
                        _spriteBatch.Draw(_spriteRight[_iSprite], _clientRect, Color.White);

                        break;
                    }
                case JUMPLEFT:
                    {
                        //Kiểm tra: Nếu _iSprite < _nSprite => Tiếp tục xử lí các lệnh bên dưới
                        if (_iSprite < 0 || _iSprite > _spriteJumpLeft.Capacity)
                            return;

                        //  Gọi hàm Draw của _spriteBatch để vẽ _sprite[_iSprite] theo _clientRect được truyền vào
                        _spriteBatch.Draw(_spriteJumpLeft[_iSprite], _clientRect, Color.White);

                        break;
                    }
                case JUMPRIGHT:
                    {
                        //Kiểm tra: Nếu _iSprite < _nSprite => Tiếp tục xử lí các lệnh bên dưới
                        if (_iSprite < 0 || _iSprite > _spriteJumpRight.Capacity)
                            return;

                        //  Gọi hàm Draw của _spriteBatch để vẽ _sprite[_iSprite] theo _clientRect được truyền vào
                        _spriteBatch.Draw(_spriteJumpRight[_iSprite], _clientRect, Color.White);

                        break;
                    }
            }
        }
    }
}
